package com.yuntu.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuntu.demo.dto.space.SpaceAddRequest;
import com.yuntu.demo.dto.space.SpaceEditRequest;
import com.yuntu.demo.dto.space.SpaceQueryRequest;
import com.yuntu.demo.entity.Space;
import com.yuntu.demo.entity.SpaceUser;
import com.yuntu.demo.entity.User;
import com.yuntu.demo.enums.SpaceLevelEnum;
import com.yuntu.demo.enums.SpaceRoleEnum;
import com.yuntu.demo.enums.SpaceTypeEnum;
import com.yuntu.demo.vo.LoginUserVO;
import com.yuntu.demo.vo.SpaceVO;
import com.yuntu.demo.vo.UserVO;
import com.yuntu.exception.ErrorCode;
import com.yuntu.exception.ThrowUtils;
import com.yuntu.exception.bizException;
import com.yuntu.mapper.SpaceMapper;
import com.yuntu.service.ISpaceService;
import com.yuntu.service.ISpaceUserService;
import com.yuntu.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 空间 服务实现类
 * </p>
 *
 * @author k
 * @since 2025-03-24
 */
@Service
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space> implements ISpaceService {
    @Resource
    IUserService userService;
    @Resource
    @Lazy
    ISpaceUserService spaceUserService;
    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    public void validSpace(Space space, boolean add) {
        //获取space参数
        ThrowUtils.throwIf(space==null, ErrorCode.PARAMS_ERROR,"空间不能为空");
        String spaceName = space.getSpaceName();
        Integer spaceLevel = space.getSpaceLevel();
        Integer spaceType = space.getSpaceType();
        SpaceLevelEnum spaceLevelEnume = SpaceLevelEnum.getEnumByValue(spaceLevel);
        SpaceTypeEnum spaceTypeEnum = SpaceTypeEnum.getEnumByValue(spaceType);
        //如果是创建，这几个参数不能为空
        if(add){
            ThrowUtils.throwIf(StrUtil.isBlank(spaceName), ErrorCode.PARAMS_ERROR,"空间名不能为空");
            ThrowUtils.throwIf(spaceLevel==null, ErrorCode.PARAMS_ERROR,"空间级别不能为空");
            ThrowUtils.throwIf(spaceLevelEnume==null, ErrorCode.PARAMS_ERROR,"输入的空间级别为空");
            ThrowUtils.throwIf(spaceType==null, ErrorCode.PARAMS_ERROR,"空间类型不能为空");
        }
        //修改数据时，以防用户修改不存在的级别
        if (spaceLevel != null && spaceLevelEnume == null) {
            throw new bizException(ErrorCode.PARAMS_ERROR,"输入的空间级别为空");
        }
        if(spaceName!=null && spaceName.length()>30){
            throw new bizException(ErrorCode.PARAMS_ERROR,"空间名需要在30字内");
        }
        if(spaceType!=null&& spaceTypeEnum ==null){
            throw new bizException(ErrorCode.PARAMS_ERROR,"输入的空间类型不存在");
        }
    }
    @Override
    public void fillSpaceBySpaceLevel(Space space) {
        SpaceLevelEnum enumByValue = SpaceLevelEnum.getEnumByValue(space.getSpaceLevel());
        if(enumByValue!=null){
            //管理员未设置-》根据级别填充
            if(space.getMaxCount()==null){
                space.setMaxCount(enumByValue.getMaxCount());
            }
            if(space.getMaxSize()==null){
                space.setMaxSize(enumByValue.getMaxSize());
            }
        }
    }

    @Override
    public long addSpace(SpaceAddRequest spaceAddRequest, LoginUserVO loginUser) {
        // 在此处将实体类和 DTO 进行转换
        Space space = new Space();
        //填充增加空间参数
        space=this.buidInsertSpace(spaceAddRequest,loginUser);
        // 默认值
        if (StrUtil.isBlank(space.getSpaceName())) {
            space.setSpaceName("默认空间");
        }
        if (space.getSpaceLevel() == null) {
            //自动设置默认空间
            space.setSpaceLevel(SpaceLevelEnum.COMMON.getValue());
        }
        if(space.getSpaceType()==null){
            //未设置类型，为私有空间
            space.setSpaceType(SpaceTypeEnum.PRIVATE.getValue());
        }
        // 填充数据
        this.fillSpaceBySpaceLevel(space);
        // 数据校验
        this.validSpace(space, true);
        // 权限校验
        if (SpaceLevelEnum.COMMON.getValue() != space.getSpaceLevel() && !userService.isAdmin(loginUser)) {
            throw new bizException(ErrorCode.NO_AUTH_ERROR, "无权限创建指定级别的空间");
        }
        // 针对用户进行加锁
        Long userId = loginUser.getId();
        String lock = String.valueOf(userId).intern();
//        Map<Long,Object> lockMap=new ConcurrentHashMap<>();
        synchronized (lock) {
            Space finalSpace = space;
            Long id = transactionTemplate.execute(status -> {
                // 先判断该用户是否没空间-》一个用户只能有一个私有空间
                boolean exists = lambdaQuery()
                        .eq(Space::getUserId, userId)
                        .eq(Space::getSpaceType,finalSpace.getSpaceType())
                        .exists();
            System.out.println("exists = " + exists);
            ThrowUtils.throwIf(exists, ErrorCode.OPERATION_ERROR, "每个用户仅能创建一个同类型空间");
                // 写入数据库
                boolean save = this.save(finalSpace);
                ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR);
                //添加成功-》如果时团队空间-》加入用户为空间管理员
                if(finalSpace.getSpaceType()==SpaceTypeEnum.TEAM.getValue()){
                    SpaceUser spaceUser = new SpaceUser();
                    spaceUser.setSpaceId(finalSpace.getId());
                    spaceUser.setUserId(userId);
                    spaceUser.setSpaceRole(SpaceRoleEnum.ADMIN.getValue());
                    boolean savaSpaceUser = spaceUserService.save(spaceUser);
                    ThrowUtils.throwIf(!savaSpaceUser, ErrorCode.OPERATION_ERROR,"添加团队空间管理员失败");
                }
                // 返回新写入的数据 id
                return finalSpace.getId();
            });
            // 返回结果是包装类，可以做一些处理
            return id == null ? -1 : id;
        }
    }
    @Override
    public Space buidInsertSpace(SpaceAddRequest spaceAddRequest, LoginUserVO loginUser) {
        Space space = new Space();
        BeanUtils.copyProperties(spaceAddRequest, space);
        space.setUserId(loginUser.getId());
        fillSpaceBySpaceLevel(space);
        return space;
    }
    @Override
    public void deleteSpace(Long id, LoginUserVO loginUser) {
        //删除空间
        //先查看空间是否存在
        Space space = this.lambdaQuery().eq(Space::getUserId, id).one();
        ThrowUtils.throwIf(space==null,ErrorCode.NOT_FOUND_ERROR,"没有该空间");
        //校验权限-》自己和管理员能删
        this.checkSpaceAuth(loginUser, space);
        boolean b = this.removeById(id);
        ThrowUtils.throwIf(b, ErrorCode.SYSTEM_ERROR);
    }
    @Override
    public void checkSpaceAuth(LoginUserVO loginUser, Space space) {
        Long spaceId = space.getId();
            if (!space.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
                throw new bizException(ErrorCode.NO_AUTH_ERROR);
            }
        }

    @Override
    public SpaceVO getSpaceVo(Space space, HttpServletRequest request) {
        // 对象转封装类
        SpaceVO spaceVO = SpaceVO.objToVo(space);
        // 关联查询用户信息
        Long userId = space.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            spaceVO.setUser(userVO);
        }
        return spaceVO;
    }

    @Override
    public QueryWrapper<Space> getQueryWrapper(SpaceQueryRequest spaceQueryRequest) {
        if(spaceQueryRequest==null){
            throw new bizException(ErrorCode.PARAMS_ERROR);
        }
        Long id = spaceQueryRequest.getId();
        Long userId = spaceQueryRequest.getUserId();
        String spaceName = spaceQueryRequest.getSpaceName();
        Integer spaceLevel = spaceQueryRequest.getSpaceLevel();
        Integer spaceType = spaceQueryRequest.getSpaceType();
        //构建查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotEmpty(id),"id",id);
        queryWrapper.eq(ObjectUtil.isNotEmpty(userId),"userId",userId);
        queryWrapper.like(ObjectUtil.isNotEmpty(spaceName),"spaceName",spaceName);
        queryWrapper.eq(ObjectUtil.isNotEmpty(spaceLevel),"spaceLevel",spaceLevel);
        queryWrapper.eq(ObjectUtil.isNotEmpty(spaceType),"spaceType",spaceType);
        String sortField = spaceQueryRequest.getSortField();
        String sortOrder = spaceQueryRequest.getSortOrder();
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }

    @Override
    public Page<SpaceVO> getSpaceVOPage(Page<Space> page, HttpServletRequest request) {
        Page<SpaceVO> voPage=new Page<>(page.getCurrent(),page.getSize(),page.getTotal());
        List<Space> spaces = page.getRecords();
        //将records转换为vo
        List<SpaceVO> spaceVOS=new ArrayList<>();
        spaces.forEach(space -> {
            spaceVOS.add(SpaceVO.objToVo(space));
        });
        //vo设置user
        //查对应的user
        spaceVOS.forEach(spaceVO -> {
            Long userId = spaceVO.getUserId();
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            spaceVO.setUser(userVO);
        });
        voPage.setRecords(spaceVOS);
        return voPage;
    }

    @Override
    public void editSpace(SpaceEditRequest spaceEditRequest,LoginUserVO loginUser) {
        //先判断是否有该空间
        if(spaceEditRequest.getId()==null){
            throw new bizException(ErrorCode.PARAMS_ERROR);
        }
        //查出数据
        Space oldSpacde = this.lambdaQuery().eq(Space::getId, spaceEditRequest.getId()).one();
        if(oldSpacde==null){
            throw new bizException(-1,"没有这张图片");
        }
        //校验数据
        this.checkSpaceAuth(loginUser, oldSpacde);
        Space space=new Space();
        BeanUtils.copyProperties(spaceEditRequest,space);
        //设置编辑时间
        space.setEditTime(LocalDateTime.now());
        //修改数据库
        boolean update = this.updateById(space);
        ThrowUtils.throwIf(!update,ErrorCode.SYSTEM_ERROR);
    }


}
